package cn.song.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.util.Precision;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Arrays;
import java.util.Date;

import static org.apache.commons.lang3.StringUtils.isBlank;


/**
 * 日期时间工具类
 *
 * @author Song~
 * @date 2023/12/15
 */
@Slf4j
@Component
public class DateUtils {


    public static void main(String[] args) {
        System.out.println("getOrderId() = " + getOrderId());
        System.out.println("getOrderId() = " + getOrderId().length());

        Date parse = DateUtil.parse("2023-12-25");
        Date parse02 = DateUtil.parse("2023-12-25");

        Date[] isNullDate02 = getIsNullDate02(parse, parse02);
        System.out.println(Arrays.toString(isNullDate02));

        // System.out.println(getEndOfDay(new Date()));

    }


    /**
     * 保留指定位数的小数 - 四舍五入
     *
     * @param number    要处理的数字
     * @param precision 保留的小数位数
     * @return 保留指定位数小数后的结果
     * @author SongRenShuo
     */
    public static double getDoublePrecision(Double number, int precision) {
        number = number == null ? 0.0 : number;

        return Precision.round(number, precision);
    }

    /**
     * 保留指定位数的小数 - 默认保留两位小数 - 四舍五入
     *
     * @param number 要处理的数字
     * @return 保留指定位数小数后的结果
     * @author SongRenShuo
     */
    public static double getDoublePrecision(Double number) {
        number = number == null ? 0.0 : number;

        return Precision.round(number, 2);
    }


    /**
     * 获取当前年份
     *
     * @param date 日期
     * @return {@link String } yyyy
     * @date 2024/03/01
     * @author SongRenShuo
     */
    public static String getYearName(Date date) {
        return new SimpleDateFormat("yyyy").format(date);
    }


    /**
     * 生成订单订单号 - 18位
     *
     * @return {@link String }
     * @date 2023/12/25
     * @author SongRenShuo
     */
    public static String getOrderId() {
        // 时间 + 随机数
        // 14 位时间戳
        String date = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
        // 4 位随机数
        String random = RandomUtil.randomNumbers(4);
        return date + random;
    }

    /**
     * 获取订单 ID Redis  - 18位+sign
     *
     * @param sign                订单号标志 - 追加至订单号末尾
     * @param stringRedisTemplate Redis
     * @param isHouZhui           sign是否拼接为后缀  - 默认/true
     * @return {@link String }
     * @date 2024/01/24
     * @author SongRenShuo
     */
    public static String getOrderIdRedis(String sign, StringRedisTemplate stringRedisTemplate, Boolean isHouZhui) {

        return getOrderIdRedisS(sign, stringRedisTemplate, isHouZhui);
    }

    /**
     * 获取订单 ID Redis  - 18位+sign
     *
     * @param sign 订单号标志 - 追加至订单号开头
     * @return {@link String }
     * @date 2024/01/24
     * @author SongRenShuo
     */
    public static String getOrderIdRedis(String sign, StringRedisTemplate stringRedisTemplate) {

        return getOrderIdRedisS(sign, stringRedisTemplate, true);
    }

    /**
     * 获取订单 ID Redis - 18位+sign
     *
     * @param sign      订单号标志 - 追加至订单号开头
     * @param isHouZhui sign是否拼接为前缀  - 默认/true
     * @return {@link String }
     * @date 2024/01/24
     * @author SongRenShuo
     */
    public static String getOrderIdRedisS(String sign, StringRedisTemplate stringRedisTemplate, Boolean isHouZhui) {
        sign = isBlank(sign) ? "" : sign;

        // 直接尝试设置订单号，直到成功为止（通常尝试次数不会很多）
        String dingdanhao = null;
        // 设置最大尝试次数
        int maxAttempts = 10;

        boolean didSetOrderNo = false;
        for (int i = 0; i < maxAttempts; i++) {
            if (isHouZhui) {
                dingdanhao = sign + getOrderId();
            } else {
                dingdanhao = getOrderId() + sign;
            }
            didSetOrderNo = Boolean.TRUE.equals(stringRedisTemplate.opsForValue()
                    .setIfAbsent(dingdanhao, "0", Duration.ofMinutes(2)));

            if (didSetOrderNo) {
                break;
            }
        }
        // 如果循环结束仍未设置成功，则抛出异常
        if (!didSetOrderNo) {
            throw new RuntimeException("订单号生成失败,请重试");
        }

        log.info("最终订单号：{}", dingdanhao);
        return dingdanhao;
    }

    /**
     * 文件名拼接时间 文件名+当前时间
     *
     * @return fileNameyyyyMMddHHmmSS
     * @author SongRenShuo
     */
    public static String getFileNameDate(String fileName) {
        return fileName + DateUtil.format(DateUtil.date(), "yyyyMMddHHmmSS");
    }

    /**
     * 获取当前日期的00:00:00
     *
     * @return {@link Date} yyyy-MM-dd 00:00:00
     * @author SongRenShuo
     */
    public static Date getStartOfDay(Date date) {
        return DateUtil.beginOfDay(date);
    }

    /**
     * 获取当前日期的23:59:59
     *
     * @return {@link Date} yyyy-MM-dd 23:59:59
     * @author SongRenShuo
     */
    public static Date getEndOfDay(Date date) {
        return DateUtil.endOfDay(date);
    }

    /**
     * 获取当前月1号0点
     *
     * @param date 日期
     * @return {@link Date} yyyy-MM-01 00:00:00
     * @author SongRenShuo
     */
    public static Date getFirstDayOfMonth(Date date) {
        // 格式化
        Date formattedDate = DateUtil.beginOfMonth(date);
        System.out.println("当月1号: " + formattedDate);
        return formattedDate;
    }

    /**
     * 获取当前月月末号23点
     *
     * @param date 日期
     * @return {@link Date} yyyy-MM-31 23:59:59
     * @author SongRenShuo
     */
    public static Date getLastDayOfMonth(Date date) {
        // 格式化
        Date formattedDate = DateUtil.endOfMonth(date);
        System.out.println("当月月末: " + formattedDate);
        return formattedDate;
    }

    /**
     * 获取年初
     *
     * @param date 日期
     * @return yyyy-01-01 00:00:00
     * @author SongRenShuo
     */
    public static Date getFirstDayOfYear(Date date) {
        return DateUtil.parse(DateUtil.format(date, "yyyy-01-01 00:00:00"));

    }

    /**
     * 获取年末
     *
     * @param date 日期
     * @return yyyy-12-31 23:59:59
     * @author SongRenShuo
     */
    public static Date getLastDayOfYear(Date date) {
        return DateUtil.parse(DateUtil.format(date, "yyyy-12-31 23:59:59"));
    }

    /**
     * 获取相差时间
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param type      类型（"year", "month", "day", "ms"）
     * @return long
     * @author SongRenShuo
     */
    public static long getBetween(Date startDate, Date endDate, String type) {
        if ("year".equals(type)) {
            return DateUtil.betweenYear(startDate, endDate, true);
        } else if ("month".equals(type)) {
            return DateUtil.betweenMonth(startDate, endDate, true);
        } else if ("day".equals(type)) {
            return DateUtil.betweenDay(startDate, endDate, true);
        } else if ("ms".equals(type)) {
            return DateUtil.betweenMs(startDate, endDate);
        }
        return 0;
    }

    /**
     * 获取相差时间（从时间戳计算）
     *
     * @param startDateTime 开始时间戳
     * @param endDateTime   结束时间戳
     * @param type          类型（"year", "month", "day", "ms"）
     * @return long
     * @author SongRenShuo
     */
    public static long getBetweenFromTimestamp(Long startDateTime, Long endDateTime, String type) {
        Date startDateDate = new Date(startDateTime);
        Date endDateDate = new Date(endDateTime);
        return getBetween(startDateDate, endDateDate, type);
    }

    /**
     * 如果为空则默认获取当天时间
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Date[] }
     * @date 2023/12/25
     * @author SongRenShuo
     */
    public static Date[] getIsNullDate(String startTime, String endTime) {
        Date startDate;
        Date endDate;
        if (isBlank(startTime)) {
            // 获取当前日期的00:00:00
            startDate = getStartOfDay(DateUtil.date());
        } else {
            startDate = getStartOfDay(DateUtil.parse(startTime));
        }
        if (isBlank(endTime)) {
            // 获取当前日期的23:59:59
            endDate = getEndOfDay(DateUtil.date());
        } else {
            endDate = getEndOfDay(DateUtil.parse(endTime));
        }
        return new Date[]{startDate, endDate};
    }


    /**
     * 如果为空则默认获取当天时间
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Date[] }
     * @date 2023/12/25
     * @author SongRenShuo
     */
    public static Date[] getIsNullDate02(Date startTime, Date endTime) {
        if (startTime == null) {
            // 获取当前日期的00:00:00
            startTime = getStartOfDay(DateUtil.date());
        } else {
            startTime = getStartOfDay(startTime);
        }
        if (endTime == null) {
            // 获取当前日期的23:59:59
            endTime = getEndOfDay(DateUtil.date());
        } else {
            endTime = getEndOfDay(endTime);
        }
        return new Date[]{startTime, endTime};
    }


    /**
     * 如果为空则默认获取当月时间
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Date[] }
     * @date 2023/12/25
     * @author SongRenShuo
     */
    public static Date[] getIsNullDateMonth(String startTime, String endTime) {
        Date startDate;
        Date endDate;
        if (isBlank(startTime)) {
            // 获取当前日期的00:00:00
            startDate = getFirstDayOfMonth(DateUtil.date());
        } else {
            startDate = getFirstDayOfMonth(DateUtil.parse(startTime));
        }
        if (isBlank(endTime)) {
            // 获取当前日期的23:59:59
            endDate = getLastDayOfMonth(DateUtil.date());
        } else {
            endDate = getLastDayOfMonth(DateUtil.parse(endTime));
        }
        return new Date[]{startDate, endDate};
    }


    /**
     * 如果为空则默认获取当月时间
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return {@link Date[] }
     * @date 2023/12/25
     * @author SongRenShuo
     */
    public static Date[] getIsNullDateMonth02(Date startTime, Date endTime) {
        if (startTime == null) {
            // 获取当前日期的00:00:00
            startTime = getFirstDayOfMonth(DateUtil.date());
        } else {
            startTime = getFirstDayOfMonth(startTime);
        }
        if (endTime == null) {
            // 获取当前日期的23:59:59
            endTime = getLastDayOfMonth(DateUtil.date());
        } else {
            endTime = getLastDayOfMonth(endTime);
        }
        return new Date[]{startTime, endTime};
    }
}

